我们在使用 Node.js 开发时,经常会用到很多命令行工具,

有些工具我们会通过 npm i -g 安装,安装完后我们就有了一个新的命令,可以在任何地方使用。

例如前面的 tsxpm2yrm 等,在随 npm 包安装的时候就完成了一些命令的注册。

本章节我们就来学习如何开发一个命令行工具,大体上和 npm 包开发一样,只有 package.json 里配置有一些不同。

PS:本章不会介绍原理,关于原理可以阅读文章:Node CLI 工具原理解析

1 初始化项目

和 npm 包开发流程一样,这里不做重复介绍 (大家可以先看 npm 开发实践),只讲过程中不一样的地方。

目录结构如下。

sh ├── package.json └── src ├── bin.ts └── index.ts

多一个 src/bin.ts 文件,将这个文件是命令行工具的入口文件。

代码如下。

```ts

!/usr/bin/env node

const argvs = process.argv.slice(2) console.log('argvs', argvs)

console.log('Hello, world!') ```

其中首行是 Hashbang,这个我们在之前的本地运行有介绍过。

Hashbang (也称为 shebang) 是一种特殊的注释,以 #! 开头,通常出现在可执行的脚本文件的第一行,用于告诉系统要使用哪个解释器来执行该脚本文件。

2 开发&构建

同样的我们这里使用 tsup 构建,支持设置多个入口文件。

json { "scripts": { "build": "tsup src/index.ts src/bin.ts --target es6 --format cjs,esm --dts", "dev": "tsup src/index.ts src/bin.ts --target es6 --format cjs,esm --dts --watch" } }

构建后会有 dist/bin.js 文件,这个就是我们最后实际运行的文件。

3 package.json bin 属性

package.json 中,我们可以配置 bin 属性,这个属性是用来指定命令行工具的入口文件的。

比如我们设置一个 hello-node 命令,将指向 dist/bin.js 文件。

json { "bin": { "hello-node": "dist/bin.js" } }

到这开发和配置基本就完成了。

4 安装&测试

4.1 项目内使用

当我们本地安装这个包的时候,就会在 node_modules/.bin 目录下生成一个 hello-node 的可执行文件,这个文件就是我们的命令行工具。

我们在这个项目里可以使用 npx hello-node 来运行这个命令。

4.2 全局使用

如果想在任意地方调用。

我们可以通过 npm link 将这个包链接到全局,然后就可以在任何地方使用 hello-node 命令了。

PS:如果这个包被发布到了 npm 上,咱们就可以直接 npm i -g xxx 直接安装启用

5 使用框架

5.1 框架介绍

框架一般主要负责的就是命令行参数的解析和校验。

社区有很多优秀的命令行框架,比如较出名的 Commandercac 等。

这里我们使用 Commander 来实践一下。

5.2 Commander 实践

① 先安装依赖

sh npm i commander

② 创建一个文件 src/commander-test.ts

加入如下内容

```ts

!/usr/bin/env node

// 引入Command类和package.json文件 import { Command } from 'commander' import pkg from '../package.json' // 创建程序实例并设置版本号 const program = new Command() program.version(pkg.version) // 添加命令hello和描述,别名为h,支持选项--exclude和--allow-dirty program .command('hello [name]') .description('打招呼') .alias('h') .option('-e, --exclude ', '排除某些文件进行扫描') .option( '--allow-dirty', '默认屏蔽以下目录(node_modules,.git等),可以设置允许' ) .action((name, options) => { console.log('你好', name, options.exclude, options.allowDirty) }) // 解析命令行参数 program.parse(process.argv) ```

然后将这个文件添加到构建指令里,构建出 dist 目录下的资源。

③ 设定指令 node-hello

package.json 中追加如下内容,一个 npm 包可以注册多个指令。

json { "bin": { "hello-node": "dist/bin.js", "node-hello": "dist/commander-test.js" } }

④ 按照上述的方式测试一下效果

可以看到框架自动为我们注册了指令和 --help 等额外选项等等。

执行效果如下。

到这里,我们就完成了一个简单的命令行工具的开发,其发布流程和 npm 包流程完全一致。

小结

本节详细的介绍了,如何使用 Node.js 开发一个命令行工具,以及如何使用框架来简化开发流程,

其中最为关键的部分就是,package.json 中的 bin 属性,用来指定命令行工具的入口文件。

使用框架,可以简化命令行参数的解析和校验,提高开发效率,并自动生成友好的提示信息。

命令行工具最终发布也是一个 npm 包,其发布流程和普通 npm 包流程完全一致。

推荐阅读

如果觉得内容不够看,推荐大家阅读: